package com.gk.panda.apis.patrol.servicr.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gk.panda.apis.patrol.commons.GeoUtils;
import com.gk.panda.apis.patrol.mapper.PatrolMapper;
import com.gk.panda.apis.patrol.servicr.AsyncPatrolService;
import com.gk.panda.apis.patrol.servicr.LocationInfoService;
import com.gk.panda.apis.patrol.servicr.PatrolService;
import com.gk.panda.pojo.patrol.entity.LocationInfoEntity;
import com.gk.panda.pojo.patrol.entity.PatrolEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：xxz
 * @Create: 2022/11/18 13:01
 */
@Service
@Slf4j
public class AsyncPatrolServiceImpl implements AsyncPatrolService {

    @Autowired
    private LocationInfoService locationInfoService;
    @Autowired
    private PatrolMapper patrolMapper;

    @Override
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void asyncCountLocation(Long patrolId) {
        try {
            long time = new Date().getTime();
            List<LocationInfoEntity> list = locationInfoService.list(new LambdaQueryWrapper<LocationInfoEntity>().eq(LocationInfoEntity::getPatrolId, patrolId).orderByAsc(LocationInfoEntity::getCreateTime));
            // 根据经纬度去重
            List<LocationInfoEntity> collect = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getLon() + "," + o.getLat()))), ArrayList::new));
            Double sum = 0.0;
            for (int i = 0; i < collect.size() - 1; i++) {
                Double distance = GeoUtils.distance(Double.parseDouble(collect.get(i).getLon()), Double.parseDouble(collect.get(i).getLat()), Double.parseDouble(collect.get(i + 1).getLon()), Double.parseDouble(collect.get(i + 1).getLat()));
                Double d = Double.parseDouble(NumberUtil.roundStr(distance, 4));
                sum += d;
            }
            Float f = 1000f;
            String route = NumberUtil.roundStr(sum, 4);
            LambdaUpdateWrapper<PatrolEntity> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(PatrolEntity::getId, patrolId);
            wrapper.set(PatrolEntity::getRoute, route);
            //计算巡护面积，公式：巡护里程（千米）* 0.2，保留4位小数
            String coverArea = NumberUtil.roundStr(NumberUtil.mul(NumberUtil.div(sum, f), 0.2).doubleValue(), 4);
            wrapper.set(PatrolEntity::getCoverArea, coverArea);
            patrolMapper.update(null, wrapper);
            log.info("计算完成,距离(米):{},巡护面积:{},巡护id:{},耗时:{},线程:{}", route, coverArea, patrolId, new Date().getTime() - time, Thread.currentThread().getName());

        } catch (Exception e) {
            log.error("异步计算距离异常{}", e);
        }
    }
}
